import axios from "axios";
import { getRequestParams } from "./utils";
import qs from "qs";

export default class CancelToken {
  static pending = new Map();
  static whiteRequest = [];
  static whiteList = {};

  constructor(options) {
    this.whiteList = options.whiteList;
  }
  /**
   * 得到该格式的url
   * @param {AxiosRequestConfig} config
   * @returns
   */
  getUrl(config) {
    const params = config.params ? config.params : {};
    const theRequest = getRequestParams(config.url);
    const transform = Object.assign(params, theRequest);
    const url = config.url.split("?")[0] + "?" + qs.stringify(transform);
    if (config.method === "get") {
      return [config.method, url].join("&");
    }
    return [config.method, config.url].join("&");
  }

  /**
   * 添加请求
   * @param {AxiosRequestConfig} config
   */
  addPending(config) {
    const url = this.getUrl(config);
    // 白名单的请求，不允许劫持
    if (this.whiteList[url]) return;
    config.cancelToken = new axios.CancelToken((cancel) => {
      if (!this.pending.has(url)) {
        this.pending.set(url, cancel);
      }
    });
  }

  /**
   * 移除请求
   * @param {AxiosRequestConfig} config
   */
  removePending(config) {
    const url = this.getUrl(config);
    const method = url.split("&")[1];
    if (this.pending.has(url) && !this.whiteRequest.includes(method)) {
      const cancel = this.pending.get(url);
      cancel && cancel(url);
      this.pending.delete(url);
    }
  }
  /**
   * 清空 pending 中的请求（在路由跳转时调用）
   */
  static clearPending() {
    for (const [url, cancel] of this.pending) {
      cancel(url);
    }
    this.pending.clear();
  }
}
